/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "nexus.h"
#include "Player.h"
#include "SpellInfo.h"

enum Spells
{
    SPELL_SPARK							= 47751,
    SPELL_RIFT_SHIELD					= 47748,
    SPELL_CHARGE_RIFTS					= 47747,
    SPELL_CREATE_RIFT					= 47743,
    SPELL_ARCANE_ATTRACTION				= 57063,
	SPELL_CLOSE_RIFTS					= 47745
};

enum Yells
{
    SAY_AGGRO							= 0,
    SAY_DEATH							= 1,
    SAY_RIFT							= 2,
    EMOTE_RIFT							= 3,
    EMOTE_SHIELD						= 4
};

enum Events
{
	EVENT_ANOMALUS_SPARK				= 1,
	EVENT_ANOMALUS_HEALTH				= 2,
	EVENT_ANOMALUS_ARCANE_ATTRACTION	= 3
};

class ChargeRifts : public BasicEvent
{
    public:
        ChargeRifts(Creature* caster) : _caster(caster)
        {
        }

        bool Execute(uint64 /*execTime*/, uint32 /*diff*/)
        {
			_caster->AI()->Talk(EMOTE_SHIELD);
			_caster->CastSpell(_caster, SPELL_CHARGE_RIFTS, true);
            return true;
        }

    private:
        Creature* _caster;
};

class boss_anomalus : public CreatureScript
{
	public:
		boss_anomalus() : CreatureScript("boss_anomalus") { }

		CreatureAI* GetAI(Creature* creature) const
		{
			return new boss_anomalusAI (creature);
		}

		struct boss_anomalusAI : public BossAI
		{
			boss_anomalusAI(Creature* creature) : BossAI(creature, DATA_ANOMALUS_EVENT)
			{
			}

			bool achievement;

			void Reset()
			{
				BossAI::Reset();
				achievement = true;
				me->CastSpell(me, SPELL_CLOSE_RIFTS, true);
			}

			uint32 GetData(uint32 data) const
			{
				if (data == me->GetEntry())
					return achievement;
				return 0;
			}

			void SetData(uint32 type, uint32)
			{
				if (type == me->GetEntry())
				{
					me->RemoveAura(SPELL_RIFT_SHIELD);
					me->InterruptNonMeleeSpells(false);
					achievement = false;
				}
			}

			void JustSummoned(Creature* summon)
			{
				summons.Summon(summon);
			}

			void EnterCombat(Unit* who)
			{
				Talk(SAY_AGGRO);
				BossAI::EnterCombat(who);

				events.SetTimer(45000);
				events.ScheduleEvent(EVENT_ANOMALUS_SPARK, 5000);
				events.ScheduleEvent(EVENT_ANOMALUS_HEALTH, 1000);
				if (IsHeroic())
					events.ScheduleEvent(EVENT_ANOMALUS_ARCANE_ATTRACTION, 8000);
			}

			void JustDied(Unit* killer)
			{
				Talk(SAY_DEATH);
				BossAI::JustDied(killer);
				me->CastSpell(me, SPELL_CLOSE_RIFTS, true);
			}

			void UpdateAI(uint32 diff)
			{
				if (!UpdateVictim())
					return;

				events.Update(diff);
				if (me->HasUnitState(UNIT_STATE_CASTING))
					return;

				switch (events.ExecuteEvent())
				{
					case EVENT_ANOMALUS_HEALTH:
						if (me->HealthBelowPct(51))
						{
							Talk(SAY_RIFT);
							Talk(EMOTE_RIFT);
							
							me->CastSpell(me, SPELL_CREATE_RIFT, false);
							me->CastSpell(me, SPELL_RIFT_SHIELD, true);
							me->m_Events.AddEvent(new ChargeRifts(me), me->m_Events.CalculateTime(1000));
							events.DelayEvents(46000);
							break;
						}
						events.ScheduleEvent(EVENT_ANOMALUS_HEALTH, 1000);
						break;
					case EVENT_ANOMALUS_SPARK:
						me->CastSpell(me->GetVictim(), SPELL_SPARK, false);
						events.ScheduleEvent(EVENT_ANOMALUS_SPARK, 5000);
						break;
					case EVENT_ANOMALUS_ARCANE_ATTRACTION:
						if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
							me->CastSpell(target, SPELL_ARCANE_ATTRACTION, false);
						events.ScheduleEvent(EVENT_ANOMALUS_ARCANE_ATTRACTION, 15000);
						break;
				}

				DoMeleeAttackIfReady();
                EnterEvadeIfOutOfCombatArea();
            }
					
			bool CheckEvadeIfOutOfCombatArea() const
			{
				return me->GetHomePosition().GetExactDist2d(me) > 60.0f;
			}
		};
};

class achievement_chaos_theory : public AchievementCriteriaScript
{
    public:
        achievement_chaos_theory() : AchievementCriteriaScript("achievement_chaos_theory")
        {
        }

        bool OnCheck(Player* /*player*/, Unit* target)
        {
            if (!target)
                return false;

			return target->GetAI()->GetData(target->GetEntry());
        }
};

void AddSC_boss_anomalus()
{
    new boss_anomalus();
	new achievement_chaos_theory();
}
